package com.example.websocket.chat.config;

import com.example.websocket.chat.bean.FastPrincipal;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.lang.Nullable;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.server.HandshakeInterceptor;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;

import java.security.Principal;
import java.util.Map;

/**
 * @author ZhenWuWang
 */
@Configuration //使用Configuration注解标识这是一个Springboot的配置类.
@EnableWebSocketMessageBroker //使用此注解来标识使能WebSocket的broker.即使用broker来处理消息.
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer
{
    @Override
    //实现WebSocketMessageBrokerConfigurer中的此方法，配置消息代理（broker）
    public void configureMessageBroker(MessageBrokerRegistry config)
    {
        //启用SimpleBroker，使得订阅到此"topic"前缀的客户端可以收到greeting消息.
        config.enableSimpleBroker("/queue","/user");
        //服务端通知客户端的前缀，可以不设置，默认为user
        config.setUserDestinationPrefix("/user");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry)
    {
        //用来注册Endpoint，“/gs-guide-websocket”即为客户端尝试建立连接的地址。
        registry.addEndpoint("/chat")
                .setHandshakeHandler(new DefaultHandshakeHandler()
                {
                    @Override
                    protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler,
                                                      Map<String, Object> attributes)
                    {
                        //将客户端标识封装为Principal对象，从而让服务端能通过getName()方法找到指定客户端
                        Object o = attributes.get("name");
                        return new FastPrincipal(o.toString());
                    }
                })
                .addInterceptors(new MyHandshakeInterceptor())
                .withSockJS();
    }
}
